home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / COMPLEX.H < prev    next >
C/C++ Source or Header  |  1992-09-28  |  17KB  |  455 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. // Copyright (C) 1992 General Electric Company.
  4. //
  5. // Permission is granted to any individual or institution to use, copy, modify,
  6. // and distribute this software, provided that this complete copyright and
  7. // permission notice is maintained, intact, in all copies and supporting
  8. // documentation.
  9. //
  10. // Texas Instruments Incorporated and General Electric Company
  11. // provides this software "as is" without express or implied warranty.
  12. //
  13. //
  14. // Created: MBN 10/25/89 -- Initial design and implementation
  15. // Updated: MBN 03/04/90 -- Added execption for DIVIDE_BY_ZERO
  16. // Updated: MJF 07/31/90 -- Added terse print
  17. // Updated: DLS 03/22/91 -- New lite version
  18. // Updated: VDN 06/29/92 -- roots of real polynomial, degree <= 4.
  19. // Updated: JAM 09/28/92 -- removed DOS specifics, stdized #includes
  20. // 
  21. // The Complex  class implements  Complex  numbers  and arithmetic.   A Complex
  22. // object has the same  precision and range of  values  as  the system built-in
  23. // type double.  Implicit conversion  to  the  system defined types short, int,
  24. // long, float,    and  double   is supported by   overloaded  operator  member
  25. // functions.  Although   the  Complex class  makes   judicous use   of  inline
  26. // functions and deals only with floating point values, the user is warned that
  27. // the Complex double arithmetic class is still  slower than  the built-in real
  28. // data types.
  29. //
  30. // The Complex   class implements common   arithmetic   exception  handling and
  31. // provides  the  application  with support  for   detecting negative infinity,
  32. // positive  infinity, overflow, and underflow as  a  result of some arithmetic
  33. // expression. If one  of these conditions  or  an attempt   to  convert from a
  34. // Complex with no value to a built-in type is detected,  an Error exception is
  35. // raised. The application programmer can provide an exception handler  to take
  36. // care of this problem. If no  such handler is  available, an error message is
  37. // printed and the application terminates.
  38. //
  39. // The Complex class requires several constants be defined to insure precision
  40. // and accuracy   of conversion.  The   preprocessor  symbols MINSHORT, MININT,
  41. // MINLONG, MAXSHORT, MAXINT, and MAXLONG  are calculated  in the <COOL/misc.h>
  42. // header file  via various  bit  manipulation  macros. The  symbols  MINFLOAT,
  43. // MINDOUBLE,  MAXFLOAT,  and MAXDOUBLE  are  system dependent  and cannot   be
  44. // calculated.  Most systems typically have  values  for these constants in the
  45. // system header  file <values.h>.  Values  for a  specific  machine should  be
  46. // copied into the <cool/misc.h> header file as necessary.
  47. //
  48. // The private data section of the Complex class contains two double  data type
  49. // slots,  one for  the real portion  and one for the  imaginary portion.   The
  50. // Complex  class  also contains   a   private  data slot  providing arithmetic
  51. // exception status.  There are four constructors for the  Complex class.   The
  52. // first is a simple inline constructor that  initializes the state and private
  53. // data slots.  The second  takes two integers (short, int,  or long)  and uses
  54. // them  as the initial value for  the object. The  second argument is optional
  55. // and if not supplied, defaults to zero.  The third takes  two reals (float or
  56. // double) and uses  them as  the  initial  value for  the object.  The  second
  57. // argument is optional  and  if not supplied, defaults  to zero.  Finally, the
  58. // fourth takes a const reference to another Complex object and  duplicates its
  59. // state and value.
  60. //
  61. // The Complex  class provides overloaded  operators for addition, subtraction,
  62. // multiplication,  division,  cosine, sine,  hyperbolic cosine  and hyperbolic
  63. // sine.  Also available are  inequality  and equality,  assignment, increment,
  64. // decrement, unary minus, and  output.  Methods to get  the real and imaginary
  65. // part are supported.  Finally,  five virtual operator conversion functions to
  66. // short, int, long, float, and double are provided.
  67. //
  68. // Find roots of a real polynomial in a single variable, with degree <=4.
  69. // Reference: Winston, P.H, Horn, B.K.P. (1984) "Lisp", Addison-Wesley.
  70.  
  71.  
  72. #ifndef COMPLEXH                // If no Complex definition
  73. #define COMPLEXH                // define the Complex symbol
  74.  
  75. #ifndef MATHH
  76. #include <math.h>        // include the standard math library
  77. #define MATHH
  78. #endif
  79.  
  80. #ifndef STREAMH            // If the Stream support not yet defined,
  81. #include <iostream.h>        // include the Stream class header file
  82. #define STREAMH
  83. #endif
  84.  
  85. #ifndef MISCELANEOUSH            // If no misc.h file
  86. #include <misc.h>            // Include useful defintions
  87. #endif    
  88.  
  89. double curt (double d);                // cubic root of a double
  90.  
  91. class CoolComplex {
  92. public:
  93.   inline CoolComplex (double real = 0, double imag = 0); // from real&imaginary
  94.   inline CoolComplex (const CoolComplex&);    // Copy constructor
  95.   inline ~CoolComplex();            // Destructor
  96.  
  97.   inline double real () const;            // Get the numerator
  98.   inline double imaginary () const;        // Get the denominator
  99.   inline N_status status () const;        // Return Number status
  100.  
  101.   inline double modulus () const;        // magnitude or norm of vector
  102.   inline double argument () const;        // angle of vector with x-axis
  103.   
  104.   CoolComplex& operator= (const CoolComplex&);        // Overload assignment
  105.   inline Boolean operator== (const CoolComplex&) const; // Overload equality
  106.   inline Boolean operator!= (const CoolComplex&) const; // Overload inequality
  107.  
  108.   inline CoolComplex invert () const;        // Return reciprical of CoolComplex
  109.   inline CoolComplex operator-() const;        // Unary minus operator
  110.   inline CoolComplex conjugate () const;    // Conjugate of complex number
  111.   inline Boolean operator!() const;        // Logical NOT operator
  112.  
  113.   /*inline##*/ friend CoolComplex operator+ (const CoolComplex&, const CoolComplex&);
  114.   /*inline##*/ friend CoolComplex operator- (const CoolComplex&, const CoolComplex&);
  115.   /*inline##*/ friend CoolComplex operator* (const CoolComplex&, const CoolComplex&);
  116.   /*inline##*/ friend CoolComplex operator/ (const CoolComplex&, const CoolComplex&);     
  117.  
  118.   inline CoolComplex& operator+= (const CoolComplex&);    // Overload add/assigne
  119.   inline CoolComplex& operator-= (const CoolComplex&);    // Overload subtract/assigne
  120.   inline CoolComplex& operator*= (const CoolComplex&);    // Overload multi/assigne
  121.   CoolComplex& operator/= (const CoolComplex&);        // Overload divide/assigne
  122.  
  123.   inline CoolComplex& operator++ ();        // Overload increment
  124.   inline CoolComplex& operator-- ();        // Overload decrement
  125.  
  126.   friend ostream& operator<< (ostream&, const CoolComplex&); 
  127.   /*inline##*/ friend ostream& operator<< (ostream&, const CoolComplex*);
  128.  
  129.   void print(ostream&);                // terse print
  130.  
  131.   inline CoolComplex cos () const;        // Cosine of a complex 
  132.   inline CoolComplex sin () const;        // Sine of a complex
  133.   inline CoolComplex tan () const;        // Tangent of a complex
  134.   inline CoolComplex cosh () const;        // Hyperbolic cosine of complex
  135.   inline CoolComplex sinh () const;        // Hyperbolic sine of complex
  136.   inline CoolComplex tanh () const;        // Hyperbolic tangent
  137.   
  138.   operator short ();                // Virtual implicit conversion
  139.   operator int ();                // Virtual implicit conversion
  140.   operator long ();                // Virtual implicit conversion
  141.   operator float ();                // Virtual implicit conversion
  142.   operator double ();                // Virtual implicit conversion
  143.  
  144.  
  145.   // finding roots of a polynomial in one variable with degree <= 4.
  146.   static int roots_of_linear (const double& a, const double& b, 
  147.                   CoolComplex& r);
  148.  
  149.   static int roots_of_quadratic (const double& a, const double& b, const double& c, 
  150.                  CoolComplex& r1, CoolComplex& r2);
  151.  
  152.   static int roots_of_cubic (const double& a, const double& b, 
  153.                  const double& c, const double& d,
  154.                  CoolComplex& r1, CoolComplex& r2, CoolComplex& r3);
  155.  
  156.   static int roots_of_quartic (const double& a, const double& b, 
  157.                    const double& c, const double& d, const double& e, 
  158.                    CoolComplex& r1, CoolComplex& r2, 
  159.                    CoolComplex& r3, CoolComplex& r4);
  160.  
  161. protected:
  162.   void minus_infinity (const char*) const;    // Raise - infinity exception
  163.   void plus_infinity (const char*) const;    // Raise + infinity exception
  164.   void overflow (const char*) const;        // Raise overflow error
  165.   void underflow (const char*) const;        // Raise overflow error
  166.   void no_conversion (const char*) const;    // Raise no conversion error
  167.   void divide_by_zero (const char*) const;    // Raise divide by zero
  168.  
  169. private:
  170.   double r;                    // Real portion
  171.   double i;                    // Imaginary portion
  172.   N_status state;                // Exception status
  173. };
  174.  
  175.  
  176. // CoolComplex -- Constructor that takes a floating point real part and optional
  177. //            floating point imaginary part to make a complex number
  178. // Input:     Double for real part, optional double for imaginary part
  179. // Output:    None
  180.  
  181. inline CoolComplex::CoolComplex (double rp, double ip) {
  182.   this->r = rp;                    // Set real part
  183.   this->i = ip;                    // Set imaginary part
  184.   this->state = N_OK;                // Set status to OK
  185. }
  186.  
  187.  
  188. // CoolComplex -- Copy constructor
  189. // Input:     Reference to CoolComplex object
  190. // Output:    None
  191.  
  192. inline CoolComplex::CoolComplex (const CoolComplex& c) {
  193.   this->r = c.r;                // Copy real part
  194.   this->i = c.i;                // Copy imaginary part
  195.   this->state = c.state;            // Copy state
  196. }
  197.  
  198. // ~CoolComplex -- Destructor does nothing
  199. // Input:     None
  200. // Output:    None
  201.  
  202. inline CoolComplex::~CoolComplex() {}        // Nothing.
  203.  
  204.  
  205. // real -- Return the real portion of the CoolComplex
  206. // Input:  None
  207. // Output: Real part of CoolComplex
  208.  
  209. inline double CoolComplex::real () const {
  210.   return this->r;                // Return real part
  211. }
  212.  
  213.  
  214. // imaginary -- Return the imaginary portion of the CoolComplex
  215. // Input:       None
  216. // Output:      Imaginary part of CoolComplex
  217.  
  218. inline double CoolComplex::imaginary () const {
  219.   return this->i;                // Return imaginary part
  220. }
  221.  
  222.  
  223. // status -- Return the status of Number
  224. // Input:    None
  225. // Output:   N_status enum value
  226.  
  227. inline N_status CoolComplex::status () const {
  228.   return this->state;
  229. }
  230.  
  231.  
  232. // modulus -- Return the magnitude or norm of Complex vector
  233.  
  234. inline double CoolComplex::modulus () const {
  235.   return sqrt((this->r * this->r) + (this->i * this->i));
  236. }
  237.  
  238. // argument -- Return the angle from x-axis to Complex vector
  239.  
  240. inline double CoolComplex::argument () const {
  241.   return atan2(this->i, this->r);
  242. }
  243.  
  244.  
  245. // operator== -- Overload the equality operator for the CoolComplex class
  246. // Input:        Reference to CoolComplex object
  247. // Output:       TRUE/FALSE
  248.  
  249. inline Boolean CoolComplex::operator== (const CoolComplex& c) const {
  250.   return (this->r == c.r && this->i == c.i);
  251. }
  252.  
  253.  
  254. // operator!= -- Overload the inequality operator for the CoolComplex class
  255. // Input:        Reference to a constant CoolComplex object
  256. // Ouput:        TRUE/FALSE
  257.  
  258. inline Boolean CoolComplex::operator!= (const CoolComplex& c) const {
  259.   return !(*this == c);
  260. }
  261.  
  262.  
  263. // operator<< -- Overload the output operator for a pointer to a CoolComplex
  264. // Input:        Ostream reference, pointer to a CoolComplex object
  265. // Output:       Ostream reference
  266.  
  267. inline ostream& operator<< (ostream& os, const CoolComplex* c) {
  268.   return operator<< (os, *c);
  269. }
  270.  
  271.  
  272. // invert -- Calculate the reciprical of a complex number
  273. // Input:    None
  274. // Output:   Reciprical of complex
  275.  
  276. inline CoolComplex CoolComplex::invert () const {
  277.   double normalize = (this->r * this->r)+(this->i * this->i);
  278.   return CoolComplex ((this->r / normalize), (-this->i / normalize));
  279. }
  280.  
  281.  
  282. // operator- -- Overload the unary minus operator for the CoolComplex class
  283. // Input:       None
  284. // Output:      Negated CoolComplex value
  285.  
  286. inline CoolComplex CoolComplex::operator- () const {
  287.   return CoolComplex (-this->r, -this->i);        // Get negative value
  288. }
  289.  
  290.  
  291. // conjugate -- Provide conjugate (that is, negate imaginary part) of complex
  292. // Input:       None
  293. // Output:      Negated CoolComplex value
  294.  
  295. inline CoolComplex CoolComplex::conjugate () const {
  296.   return CoolComplex (this->r, -this->i);        // Get negative value
  297. }
  298.  
  299.  
  300. // operator! -- Overload the negation operator for the CoolComplex class
  301. // Input:       None
  302. // Output:      TRUE/FALSE
  303.  
  304. inline Boolean CoolComplex::operator! () const {
  305.   return ((this->r == 0.0) ? TRUE : FALSE);    // Return logical state
  306. }
  307.  
  308.  
  309. // operator++ -- Overload the increment operator for the CoolComplex class
  310. // Input:        None
  311. // Output:       Reference to updated CoolComplex object
  312.  
  313. inline CoolComplex& CoolComplex::operator++ () {
  314.   this->r++ ;                    // Increment real part
  315.   return *this;                    // Return updated object
  316. }
  317.   
  318.  
  319. // operator-- -- Overload the decrement operator for the CoolComplex class
  320. // Input:        None
  321. // Output:       Reference to updated CoolComplex object
  322.  
  323. inline CoolComplex& CoolComplex::operator-- () {
  324.   this->r--;                    // Decrement real part
  325.   return *this;                    // Return updated object
  326. }
  327.  
  328.  
  329. // operator+ -- Overload the addition operator for the CoolComplex class
  330. // Input:       Reference to complex object
  331. // Output:      Reference to new complex object
  332.  
  333. inline CoolComplex operator+ (const CoolComplex& c1, const CoolComplex& c2) {
  334.   return CoolComplex (c1.real()+c2.real(), c1.imaginary()+c2.imaginary());
  335. }
  336.  
  337.  
  338. // operator- -- Overload the subtraction operator for the CoolComplex class
  339. // Input:       Reference to CoolComplex object
  340. // Output:      Reference to new CoolComplex object
  341.  
  342. inline CoolComplex operator- (const CoolComplex& c1, const CoolComplex& c2) {
  343.   return CoolComplex (c1.real()-c2.real(), c1.imaginary()-c2.imaginary());
  344. }
  345.  
  346.  
  347. // operator* -- Overload the multiplication operator for the CoolComplex class
  348. // Input:       Reference to complex object
  349. // Output:      Reference to new complex object
  350.  
  351. inline CoolComplex operator* (const CoolComplex& c1, const CoolComplex& c2) {
  352.   return CoolComplex (((c1.r * c2.r)-(c1.i * c2.i)),
  353.               ((c1.r * c2.i)+(c1.i * c2.r)));
  354. }
  355.  
  356.  
  357. // operator/ -- Overload the division operator for the CoolComplex class
  358. // Input:       Reference to complex object
  359. // Output:      Reference to new complex object
  360.  
  361. inline CoolComplex operator/ (const CoolComplex& c1, const CoolComplex& c2) {
  362.   CoolComplex result = c1;
  363.   result /= c2;
  364.   return result;
  365. }
  366.  
  367.  
  368. // operator+= -- Overload the addition/assign operator for the CoolComplex class
  369. // Input:        Reference to complex object
  370. // Output:       None
  371.  
  372. inline CoolComplex& CoolComplex::operator+= (const CoolComplex& c) {
  373.   this->r += c.r;                // Add real part
  374.   this->i += c.i;                // Add imaginary part
  375.   return *this;
  376. }
  377.  
  378.  
  379. // operator-= -- Overload the subtraction/assign operator for the CoolComplex class
  380. // Input:        Reference to complex object
  381. // Output:       None
  382.  
  383. inline CoolComplex& CoolComplex::operator-= (const CoolComplex& c) {
  384.   this->r -= c.r;                // Subtract real part
  385.   this->i -= c.i;                // Subtract imaginary part
  386.   return *this;
  387. }
  388.  
  389.  
  390. // operator*= -- Overload the multiplication/assign operator for CoolComplex class
  391. // Input:        Reference to complex object
  392. // Output:       None
  393.  
  394. inline CoolComplex& CoolComplex::operator*= (const CoolComplex& c) {
  395.   this->r = (this->r * c.r)-(this->i * c.i);    // Multiply real part
  396.   this->i = (this->r * c.i)+(this->i * c.r);    // Multiply imaginary part
  397.   return *this;
  398. }
  399.  
  400.  
  401. // sin --  Calculate the sine of a CoolComplex number
  402. // Input:  Reference to a complex
  403. // Output: Reference to a new complex whose value is the answer
  404.  
  405. inline CoolComplex CoolComplex::sin () const {
  406.   return CoolComplex (::sin (this->r), ::sin (this->i));
  407. }
  408.  
  409.  
  410. // cos --  Calculate the cosine of a Complex number
  411. // Input:  Reference to a complex
  412. // Output: Reference to a new complex whose value is the answer
  413.  
  414. inline CoolComplex CoolComplex::cos () const {
  415.   return CoolComplex (::cos (this->r), ::cos (this->i));
  416. }
  417.  
  418.  
  419. // tan --  Calculate the tangent of a CoolComplex number
  420. // Input:  Reference to a complex
  421. // Output: Reference to a new complex whose value is the answer
  422.  
  423. inline CoolComplex CoolComplex::tan () const {
  424.   return CoolComplex (::tan (this->r), ::tan (this->i));
  425. }
  426.  
  427.  
  428. // sinh -- Calculate the hyperbolic sine of a CoolComplex number
  429. // Input:  Reference to a complex
  430. // Output: Reference to a new complex whose value is the answer
  431.  
  432. inline CoolComplex CoolComplex::sinh () const {
  433.   return CoolComplex (::sinh (this->r), ::sinh (this->i));
  434. }
  435.  
  436.  
  437. // cosh -- Calculate the hyperbolic cosine of a CoolComplex number
  438. // Input:  Reference to a complex
  439. // Output: Reference to a new complex whose value is the answer
  440.  
  441. inline CoolComplex CoolComplex::cosh () const {
  442.   return CoolComplex (::cosh (this->r), ::cosh (this->i));
  443. }
  444.  
  445.  
  446. // tanh -- Calculate the hyperbolic tangent of a CoolComplex number
  447. // Input:  Reference to a complex
  448. // Output: Reference to a new complex whose value is the answer
  449.  
  450. inline CoolComplex CoolComplex::tanh () const {
  451.   return CoolComplex (::tanh (this->r), ::tanh (this->i));
  452. }
  453.  
  454. #endif COMPLEXH                    // End COMPLEXH
  455.